﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web.Security;
using System.Xml;
using WeiXinSDK.Core;
using WeiXinSDK.DataModel;

namespace WeiXinSDK
{
    public class WeiXin
    {

        public static void EventRequest(IWeiXinEvent WeiXinEvent)
        {
            string postStr = "";
            System.Web.HttpRequest Request = System.Web.HttpContext.Current.Request;
            try
            {
                if (Request.HttpMethod.ToLower() == "post")
                {
                    Stream s = Request.InputStream;
                    byte[] b = new byte[s.Length];
                    s.Read(b, 0, (int)s.Length);
                    postStr = Encoding.UTF8.GetString(b);

                    if (!string.IsNullOrEmpty(postStr)) //请求处理
                    {
                        Handle(postStr, WeiXinEvent);
                    }
                }
                else
                {
                    Auth();
                }
            }
            catch (Exception ex)
            {
                Loggers.WeinXinLogger.Error(ex);
            }
        }

        private static void Handle(string Content, IWeiXinEvent WeiXinEvent)
        {

            Content = Content.Replace("<xml>", "<RequestXML>").Replace("</xml>", "</RequestXML>");
            RequestXML requestXML = Core.Utility.ConvertToObject<RequestXML>(Content);
            requestXML.AppCode = System.Web.HttpContext.Current.Request["AppCode"];
            
            ResponseMsg(requestXML, WeiXinEvent);
        }

        private delegate void AsyncEventHandler(RequestXML RequestXML);

        /// <summary>
        /// 回复消息(微信信息返回)
        /// </summary>
        /// <param name="weixinXML"></param>
        private static void ResponseMsg(RequestXML RequestXML, IWeiXinEvent WeiXinEvent)
        {
            try
            {
                string msg = string.Empty;

                if (WeiXinConfig.IsCertified)
                {
                    //异步响应结果，即通过发送客服消息接口返回结果，适合对于相应时间过长的操作。需认证公众号。
                    AsyncEventHandler asy = new AsyncEventHandler(WeiXinEvent.AsyncProcess);
                    IAsyncResult ia = asy.BeginInvoke(RequestXML, null, null);
                }
                else
                {
                    //同步相应结果。无需认证公众号
                    Message result = WeiXinEvent.SyncProcess(RequestXML);
                    msg = result != null ? Core.Utility.ConvertToXmlString<Message>(result) : string.Empty;  //返回响应结果    
                    Loggers.WeinXinLogger.InfoFormat("回复消息(微信信息返回){0}", msg);
                }

                System.Web.HttpContext.Current.Response.Write(msg);
            }
            catch (Exception ex)
            {
                Loggers.WeinXinLogger.FatalFormat("系统相应失败。ResponseMsg==>{0}", ex);
                System.Web.HttpContext.Current.Response.Write(string.Empty);
            }
        }

        public static void Auth()
        {
            string echoStr = System.Web.HttpContext.Current.Request.QueryString["echoStr"];
            if (CheckSignature())
            {
                if (!string.IsNullOrEmpty(echoStr))
                {
                    System.Web.HttpContext.Current.Response.Write(echoStr);
                    System.Web.HttpContext.Current.Response.End();
                }
            }
        }

        /// <summary>
        /// 验证微信签名
        /// </summary>
        /// * 将token、timestamp、nonce三个参数进行字典序排序
        /// * 将三个参数字符串拼接成一个字符串进行sha1加密
        /// * 开发者获得加密后的字符串可与signature对比，标识该请求来源于微信。
        /// <returns></returns>
        private static bool CheckSignature()
        {
            string signature = System.Web.HttpContext.Current.Request.QueryString["signature"];
            string timestamp = System.Web.HttpContext.Current.Request.QueryString["timestamp"];
            string nonce = System.Web.HttpContext.Current.Request.QueryString["nonce"];
            string[] ArrTmp = { WeiXinConfig.Token, timestamp, nonce };
            Array.Sort(ArrTmp);     //字典排序
            string tmpStr = string.Join("", ArrTmp);
            tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
            tmpStr = tmpStr.ToLower();
            if (tmpStr == signature)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
